# 24. 对象、类名称空间,组合


# 对象/类名称空间

说到对象/类名称空间,那就要先了解一下类跟对象的运行结构

class so:
    name = "人类"
    age = "一百岁左右"
    faile = "信仰"

    def __init__(self,nameb,ageb,faileb):
        self.nameb = nameb
        self.ageb = ageb
        self.faileb = faileb

    def wo(self):
        print("人与人的区别到底是什么")

    def eo(self):
        print("你说的,明天会更好")
ll = so("江心",18,"唯我") 


##这里就用话来简单写点执行过程

#============================当程序执行时遇到类时产生的类名称空间存储的数据============================
程序执行,从头到尾
遇到so类,执行so类以下可以被执行的代码--这里被执行就会生成一个类名称空间
遇到name变量,执行并记录在类名称空间中
遇到age变量,执行并记录在类名称空间中
遇到faile变量,执行并记录在类名称空间中
遇到__init__方法,记录保存内存地址
遇到wo方法,记录保存内存地址
遇到eo方法,记录保存内存地址


#============================当类加()执行赋值给变量时,会执行实例化过程============================
当类进入实例化过程时会生成一个空间,称为实例化空间,也叫做对象名称空间
将生成的实例化空间的内存地址返回给init函数中的self参数
将so()括号中的数据传递给init方法中的参数,并执行记录在实例化空间
当传递完毕,实例化空间会自动生成一个指示牌(用于保存类对象指针),有了指示牌实例化空间才能找到类名称空间,开始封闭空间,并把内存地址赋值给变量ll

注意:如果有多个实例化过程,那么产生的多个实例化空间之间都是单独的个体对象



# 查询顺序

类跟对象查询数据的顺序

nameb = "凡"
class so:
    name = "人类"
    age = "一百岁左右"
    faile = "信仰"

    def __init__(self,nameb,ageb,faileb):
        self.nameb = nameb
        self.ageb = ageb
        self.faileb = faileb

    def wo(self):
        print("人与人的区别到底是什么")

    def eo(self):
        print("你说的,明天会更好")

  1. 对象.属性 : 先从对象空间找,如果找不到,再从类空间找,再找不到,再从父类找....

    ll = so("江心",18,"唯我")
    print(ll.name)
    
    执行结果:
    人类
    

    ​ 以上实例,对象如果在当前方法中找不到,那就会去类空间找


  1. 类名.属性 : 先从本类空间找,如果找不到,再从父类找....

    ll = so("江心",18,"唯我")
    print(so.nameb)
    
    执行结果:
    AttributeError: type object 'so' has no attribute 'nameb'  #报错
    

    ​ 以上实例,类如果在当前类中找不到,就会去父类找,如果找不到报错



# 小练习

计算程序中实例化多少次

class so:
    name = "人类"
    age = "一百岁左右"
    faile = "信仰"
    count = 0

    def __init__(self,nameb,ageb,faileb):
        self.nameb = nameb
        self.ageb = ageb
        self.faileb = faileb
        so.count += 1

    def wo(self):
        print("人与人的区别到底是什么")

    def eo(self):
        print("你说的,明天会更好")
ll1 = so("江心",18,"唯我")
ll2 = so("江凡",13,"唯我")
ll3 = so("江空",23,"唯我")
print(so.count)

注意:在对象引用类中的静态变量时,只能查询,不能增删改操作,如果要使用对象进行修改类中的变量,那么可以修改成功,在实例化一个对象来查看这个类的变量时,就会发现这个类的变量还是原先的值

总结:可以使用对象进行操作,不过操作的结果是记录在了该对象的实例化空间,不会影响到类空间里面记录的静态数据



# 进阶题 (看组合之前必须先做)

# 要求

模拟英雄联盟写一个游戏人物的类
  要求:
  (1)创建一个 Game_role的类.
  (2) 构造方法中给对象封装name,ad(攻击力),hp(血量).三个属性.
  (3) 创建一个attack方法,此方法是实例化两个对象,互相攻击的功能:: 实例化一个对象 盖伦,ad为10, hp为100
      实例化另个一个对象 剑豪 ad为20, hp为80
      盖伦通过attack方法攻击剑豪,此方法要完成 '谁攻击谁,谁掉了多少血,  还剩多少血'的提示功能.

# 答案

class so:
    def __init__(self,name,ad,hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def wo(self,amdc):
        amdc.hp = amdc.hp - self.ad
        print(
        """
            攻击提示:
                你的英雄%s攻击了对方英雄%s
                对方英雄%s,掉了%s滴血
                对方英雄%s,还剩下%s滴血
        """
        %(self.name,amdc.name,amdc.name,self.ad,amdc.name,amdc.hp)
        )

amdc1 = so("盖伦",10,100)
amdc2 = so("剑豪",20,80)
amdc1.wo(amdc2)


# 组合

组合是什么:给一个类的对象封装一个属性,这个属性是另一个类的对象,组合的原理就完全包含在这话中,接下来要深入下面的实验来理解组合的用法


# 实验

在上面进阶题为基础,新增武器系统


# 从网上截个来的

class GameRole:
    def __init__(self, name, ad, hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def attack(self,p):
        p.hp = p.hp - self.ad
        print('%s 攻击 %s,%s 掉了%s血,还剩%s血' %(self.name,p.name,p.name,self.ad,p.hp))

    def armament_weapon(self,wea):
        self.wea = wea


class Weapon:
    def __init__(self,name,ad):
        self.name = name
        self.ad = ad
    def fight(self,p1,p2):
        p2.hp = p2.hp - self.ad
        print('%s 用%s打了%s,%s 掉了%s血,还剩%s血'\
              % (p1.name,self.name,p2.name,p2.name,self.ad,p2.hp))

p1 = GameRole('大阳哥',20,500)
p2 = GameRole('印度阿宁',50,200)
axe = Weapon('三板斧',60)
broadsword = Weapon('屠龙宝刀',100)
p1.armament_weapon(axe)  # 给大阳哥 装备了三板斧这个对象.
p1.wea.fight(p1,p2)

比较重点的点

  1. axe:是通过实例化出来的变量,就是说这个变量中其实是实例化空间的内存地址
  2. 先把axe变量传递给GameRole类中的armament_weapon方法中
  3. 在通过p1来调用armament_weapon方法中的wea变量来调用Weapon类中的fight方法

# 博主写的

class weapon:
    def __init__(self,name,ap):
        self.name = name
        self.ap = ap

class so:
    def __init__(self,name,ad,hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def wo(self,amdc,wea):
        self.weapon(wea)
        amdc.hp = amdc.hp - (self.ad + self.weapon.ap )
        ad = self.ad + self.weapon.ap
        print(
        """
            攻击提示:
                你的英雄%s使用%s攻击对方英雄%s
                对方英雄%s,掉了%s滴血
                对方英雄%s,还剩下%s滴血
        """
        %(self.name,self.weapon.name,amdc.name,amdc.name,ad,amdc.name,amdc.hp)
        )
    def weapon(self,wea):
        self.weapon = wea

dagger = weapon("短剑",60)
dorans = weapon("多兰之刃",120)
stormblade = weapon("暴风之剑",180)
amdc1 = so("盖伦",10,100)
amdc2 = so("剑豪",20,80)

amdc2.wo(amdc1,dagger)

​ 以上的实验跟上一个的实验小异大同